#include "CamCaptureCavas.h"
#include "process.h"
#include "CvxWin32.h"
#include <QPainter>
#include <QPaintEngine>
#include <iostream>
struct SuppressVideoInputMessages
{
	SuppressVideoInputMessages() { videoInput::setVerbose(false); }
};

static SuppressVideoInputMessages do_it;
videoInput CCamCaptureCavas::VI;

CCamCaptureCavas::CCamCaptureCavas(OCEANUI::CMainWindowBase* parent):
	CCentralCanvasBase(parent),
	pCurrentImg_(NULL)
{
	//index = -1;
	frame = 0;
	setAttribute(Qt::WA_NoBackground);
	resize(800,600); 
	setVisible(true);
	bool connectResult = connect(this,SIGNAL(SigUpdate()),this,SLOT(repaint ()),Qt::ConnectionType::QueuedConnection);
	assert(connectResult);
	InitializeCriticalSection(&imagelock_);
	
}

void CCamCaptureCavas::close()
{
	if( index_ >= 0 )
	{
		VI.stopDevice(index_);
		index_ = -1;
		cvReleaseImage(&frame);
	}
}

// Initialize camera input
bool CCamCaptureCavas::open( int _index )
{
	close();
	VI.setupDevice(_index);
	if( !VI.isDeviceSetup(_index) )
		return false;
	return true;
}

bool CCamCaptureCavas::grabFrame()
{
	return true;
}


IplImage* CCamCaptureCavas::retrieveFrame()
{
	if( !frame || VI.getWidth(index_) != frame->width || VI.getHeight(index_) != frame->height )
	{
		cvReleaseImage( &frame );
		int w = VI.getWidth(index_), h = VI.getHeight(index_);
		frame = cvCreateImage( cvSize(w,h), 8, 3 );
	}

	VI.getPixels( index_, (uchar*)frame->imageData, false, true );
	return frame;
}

double CCamCaptureCavas::getProperty( int property_id )
{
	switch( property_id )
	{
	case CV_CAP_PROP_FRAME_WIDTH:
		return VI.getWidth(index_);
	case CV_CAP_PROP_FRAME_HEIGHT:
		return VI.getHeight(index_);
	case CV_CAP_PROP_FOURCC:
		return 0;
	}
	return 0;
}

bool CCamCaptureCavas::setProperty( int property_id, double value )
{
	int width = 0, height = 0;

	switch( property_id )
	{
	case CV_CAP_PROP_FRAME_WIDTH:
		width = cvRound(value);
		height = width*3/4;
		break;
	case CV_CAP_PROP_FRAME_HEIGHT:
		height = cvRound(value);
		width = height*4/3;
	default:
		return false;
	}

	if( width != VI.getWidth(index_) || height != VI.getHeight(index_) )
	{
		VI.stopDevice(index_);
		VI.setupDevice(index_, width, height);
	}
	return VI.isDeviceSetup(index_);
}

void CCamCaptureCavas::initData( void* pData )
{
	close();
	index_ = videoInput::listDevices() - 1;
	VI.setupDevice(index_);
	if( !VI.isDeviceSetup(index_) )
		std::cout<<"Set up Cam falied"<<std::endl;

	fps_ = 23;//getProperty(pCapture_,CV_CAP_PROP_FPS);
	_beginthread(captureThreadCallBack,0,this);
}

void CCamCaptureCavas::syncVideoImage( IplImage* pImg )
{
	ResourceLocker lock(&imagelock_);
	if (NULL != pCurrentImg_)
	{
		cvReleaseImage(&pCurrentImg_);
	}
	pCurrentImg_ = pImg;
	emit SigUpdate();
}

void CCamCaptureCavas::paintEvent( QPaintEvent *event )
{
	if (NULL == pCurrentImg_)
	{
		return;
	}
	QPainter painter(this);
	QRect qrc = this->geometry();
	ResourceLocker lock(&imagelock_);
	CvRect rc =cvRect(qrc.x(),qrc.y(),pCurrentImg_->width,pCurrentImg_->height);
	CvxWin32::DrawToHDC(pCurrentImg_,painter.paintEngine()->getDC(),&rc);
}

void __cdecl captureThreadCallBack(void* pData)
{
	CCamCaptureCavas* pCamCapture = reinterpret_cast<CCamCaptureCavas*>(pData);
	 
	bool bRunning = true;
	IplImage* pImg = NULL;
	int waitTime = cvRound((1./pCamCapture->fps_) * 1000);
	while ( bRunning)
	{
		pImg= pCamCapture->retrieveFrame();  
		if (NULL == pImg)
		{
			bRunning = false;
			break;
		}
		IplImage* pImgCpy = cvCloneImage(pImg);
		//maybe it's too slow
		//TODO: record pannel want to hook this event
		OCEANUI::CMainWindowBase::gInstance().onEventChanged(pImg,pCamCapture);
		pCamCapture->syncVideoImage(pImgCpy);
		Sleep(waitTime);
		//std::cout << xx << std::endl;
	}
}

//CvCapture* cvCreateCameraCapture_DShow( int index )
//{
//	CCamCaptureCavas* capture = new CCamCaptureCavas;
//
//	if( capture->open( index ))
//		return capture;
//
//	delete capture;
//	return 0;
//}
